package com.own.component.common.base.service.hook;

import com.own.component.common.base.entity.BaseMap;
import com.own.component.common.base.entity.BaseQuery;
import com.own.component.common.base.entity.po.BaseBean;
import com.own.component.common.base.entity.vo.BaseBeanVo;
import com.own.component.common.em.SystemEnum;
import com.own.component.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;

/**
 * AbstractBaseHook
 *
 * @author chenxueli
 * @date 2023-10-18 11:30:29
 */
@Slf4j
@Service
public abstract class AbstractBaseHook<
        PO extends BaseBean,
        VO extends BaseBeanVo<PO>,
        MAP extends BaseMap<PO>,
        QUERY extends BaseQuery
        > implements BaseGetHook<PO, VO>, BaseAddHook<PO, VO>, BaseUpdateHook<PO, VO>, BaseDeleteHook, BaseWrapperHook<PO, QUERY> {

    /**
     * po对象的构造方法
     */
    private Constructor<PO> poConstructor = null;
    /**
     * vo对象的构造方法
     */
    private Constructor<VO> voConstructor = null;
    /**
     * map对象的构造方法
     */
    private Constructor<MAP> mapVoConstructor = null;
    /**
     * query对象的构造方法
     */
    private Constructor<QUERY> queryConstructor = null;

    @SuppressWarnings("all")
    public AbstractBaseHook() {
        var array = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
        // 必须是六个参数才能使用
        if (array.length == 6) {
            Class<PO> poClass = (Class<PO>) array[0];
            try {
                poConstructor = poClass.getConstructor();
            } catch (Exception e) {
                log.error("{}无参构造方法获取失败", poClass.getName());
            }
            Class<VO> voClass = (Class<VO>) array[2];
            try {
                voConstructor = voClass.getConstructor(poClass);
            } catch (Exception e) {
                log.error("{}的po构造方法获取失败", voClass.getName());
            }
            Class<MAP> mapVoClass = (Class<MAP>) array[3];
            try {
                mapVoConstructor = mapVoClass.getConstructor(poClass);
            } catch (Exception e) {
                log.error("{}的po构造方法获取失败", mapVoClass.getName());
            }
            Class<QUERY> queryClass = (Class<QUERY>) array[4];
            try {
                queryConstructor = queryClass.getConstructor();
            } catch (Exception e) {
                log.error("{}无参构造方法获取失败", queryClass.getName());
            }
        }
    }

    /**
     * 根据po对象生成vo对象
     *
     * @param po po对象
     * @return vo对象
     */
    @SuppressWarnings("all")
    protected VO ofVo(PO po) {
        if (voConstructor == null) {
            throw new BusinessException(SystemEnum.VO_CONSTRUCTOR_ERROR);
        }
        if (po == null) {
            return null;
        }
        try {
            return voConstructor.newInstance(po);
        } catch (Exception e) {
            throw new BusinessException(SystemEnum.VO_CONSTRUCTOR_ERROR);
        }
    }

    /**
     * 根据po对象生成mapVo对象
     *
     * @param po po对象
     * @return mapVo对象
     */
    @SuppressWarnings("all")
    protected MAP ofMap(PO po) {
        if (mapVoConstructor == null) {
            throw new BusinessException(SystemEnum.MAP_CONSTRUCTOR_ERROR);
        }
        if (po == null) {
            return null;
        }
        try {
            return mapVoConstructor.newInstance(po);
        } catch (Exception e) {
            throw new BusinessException(SystemEnum.MAP_CONSTRUCTOR_ERROR);
        }
    }

    /**
     * 生成query对象
     *
     * @return query对象
     */
    @SuppressWarnings("all")
    protected PO newPoInstance() {
        if (poConstructor == null) {
            throw new BusinessException(SystemEnum.PO_CONSTRUCTOR_ERROR);
        }
        try {
            return poConstructor.newInstance();
        } catch (Exception e) {
            throw new BusinessException(SystemEnum.PO_CONSTRUCTOR_ERROR);
        }
    }

    /**
     * 生成query对象
     *
     * @return query对象
     */
    @SuppressWarnings("all")
    protected QUERY newQueryInstance() {
        if (queryConstructor == null) {
            throw new BusinessException(SystemEnum.QUERY_CONSTRUCTOR_ERROR);
        }
        try {
            return queryConstructor.newInstance();
        } catch (Exception e) {
            throw new BusinessException(SystemEnum.QUERY_CONSTRUCTOR_ERROR);
        }
    }

}
